package com.zzu.base.service.impl;

import com.zzu.base.common.enums.ResultStatusEnum;
import com.zzu.base.exception.ProcessException;
import com.zzu.base.service.ResourceDownloadService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@Slf4j
@Service
public class ResourceDownloadServiceImpl implements ResourceDownloadService {

    @Value("${file.storage-root}")
    private String storageRoot;

    @Override
    public void downloadByRelativePath(String relativePath, HttpServletResponse response) {
        // 1. 校验参数
        if (relativePath == null || relativePath.trim().isEmpty()) {
            throw new ProcessException(ResultStatusEnum.BAD_REQUEST, "文件路径不能为空");
        }

        // 2. 构建本地文件完整路径
        // 处理相对路径中的分隔符（统一转换为系统分隔符）
        String systemRelativePath = relativePath.replace("/", File.separator).replace("\\", File.separator);
        File targetFile = new File(storageRoot, systemRelativePath); // 自动拼接根目录和相对路径

        // 3. 校验文件是否存在
        if (!targetFile.exists() || !targetFile.isFile()) {
            log.warn("文件不存在，路径：{}", targetFile.getAbsolutePath());
            throw new ProcessException(ResultStatusEnum.NOT_FOUND, "文件不存在或已删除");
        }

        // 4. 设置响应头（支持中文文件名）
        String fileName = targetFile.getName();
        try {
            response.reset();
            response.setCharacterEncoding("utf-8");
            // 编码文件名，解决中文乱码
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
            // 设置为附件下载（attachment），也可改为 inline 在线预览
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
            // 设置文件大小
            response.setContentLengthLong(targetFile.length());
            // 设置MIME类型（默认二进制流）
            response.setContentType("application/octet-stream");
        } catch (UnsupportedEncodingException e) {
            log.error("文件名编码失败，文件名：{}", fileName, e);
            throw new ProcessException(ResultStatusEnum.INTERNAL_SERVER_ERROR, "文件下载失败");
        }

        // 5. 输出文件流
        try (InputStream in = new FileInputStream(targetFile);
             OutputStream out = response.getOutputStream()) {

            byte[] buffer = new byte[1024 * 8]; // 8KB缓冲区
            int len;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush(); // 确保所有数据写入响应
            log.debug("文件下载成功，路径：{}", targetFile.getAbsolutePath());

        } catch (IOException e) {
            log.error("文件流输出失败，路径：{}", targetFile.getAbsolutePath(), e);
            throw new ProcessException(ResultStatusEnum.INTERNAL_SERVER_ERROR, "文件下载失败");
        }
    }
}